// package: rewords-server-2024
// filename: admin
// author: diogoxiang@gmail.com
// time: 2024/11/11 14:54

package admin

import (
	"context"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"go.mongodb.org/mongo-driver/bson"

	"rewords-server-2024/api/admin"
	"rewords-server-2024/internal/consts"
	"rewords-server-2024/internal/library/ecode"
	"rewords-server-2024/internal/logic/mgx"
	"rewords-server-2024/internal/model/entity"
	"rewords-server-2024/internal/model/input/form"
	"rewords-server-2024/internal/model/input/query_in"
	"rewords-server-2024/internal/service"
	"rewords-server-2024/utility/ufun"
	"rewords-server-2024/utility/ztime"
)

var Dict = new(cDict)

type cDict struct {
}

// AddDict 添加字典
func (c *cDict) AddDict(ctx context.Context, req *admin.DictAddReq) (res *admin.DictAddRes, err error) {

	Doc := &entity.SysDict{
		Group:     req.Group,
		GroupName: req.GroupName,
		Label:     req.Label,
		Value:     req.Value,
		Remark:    req.Remark,
		Status:    req.Status,
		Etype:     "dict",
	}

	eid, err := mgx.GetAutoInc("dict")
	if err != nil {
		// 处理错误，例如记录日志或返回错误信息
		g.Log().Printf(ctx, "Failed to get auto increment value for user: %v", err)
		// 根据实际情况决定如何处理错误，例如返回一个错误值或中断程序
		return nil, gerror.NewCode(ecode.InvalidParams)
	}
	Doc.ID = int64(eid)
	Doc.SetTimeValue(0)
	Doc.SetTimeValue(1)

	err = service.Mgx().InsertOne(ctx, consts.CConfig, Doc)

	if err != nil {
		g.Log().Error(ctx, "Insert error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	return &admin.DictAddRes{}, nil
}

func (c *cDict) QueryList(ctx context.Context, req *admin.DictListReq) (res *admin.DictListRes, err error) {

	// 添加 etype="dict" 条件
	etypeCondition := query_in.Condition{
		Field:         "etype",
		ConditionType: query_in.ConditionTypeEq,
		Vals:          []any{"dict"},
		Op:            query_in.OpAnd,
	}

	if req.Conditions == nil {
		req.Conditions = []query_in.Condition{etypeCondition}
	} else {
		req.Conditions = append(req.Conditions, etypeCondition)
	}

	query, skip, limit, sort, _ := query_in.BuildMongoQueryWithPage(req.Conditions, req.OrderFields, req.Page, nil)
	g.Log().Debug(ctx, "MongoDB query conditions:", query)
	g.Log().Debug(ctx, "Skip:", skip, "Limit:", limit)

	// 查询数据
	result, err := service.Mgx().Find(ctx, consts.CConfig, query, nil, skip, limit, sort)
	if err != nil {
		return nil, gerror.Wrap(err, "获取数据失败")
	}

	var data []entity.SysDict
	if err = gconv.Struct(result, &data); err != nil {
		return nil, gerror.Wrap(err, "数据转换失败")
	}

	var total int64

	if req.Page.QueryCount {
		// 获取总记录数
		total, err = service.Mgx().CountDocuments(ctx, consts.CConfig, query)
		if err != nil {
			return nil, gerror.Wrap(err, "获取总记录数失败")
		}
	}

	res = &admin.DictListRes{
		Data: ufun.If(len(data) > 0, data, []entity.SysDict{}),
		PageResult: query_in.PageResult{
			Current:  (skip / limit) + 1,
			PageSize: limit,
			Total:    total,
			Pages:    (total + limit - 1) / limit,
			HasNext:  (skip + limit) < total,
		},
	}

	return res, nil
}

func (c *cDict) QueryInfo(ctx context.Context, req *admin.DictInfoReq) (res *admin.DictInfoRes, err error) {

	selectMap := bson.M{
		"id":     req.Id,
		"etype":  "dict",
		"status": "normal",
	}
	result, err := service.Mgx().FindOne(ctx, consts.CConfig, selectMap, nil)

	if err != nil {
		return nil, gerror.NewCode(gcode.CodeNotImplemented)
	}

	var entity entity.SysDict
	if err = gconv.Struct(result, &entity); err != nil {
		return nil, gerror.Wrap(err, "数据转换失败")
	}

	return &admin.DictInfoRes{
		entity,
	}, nil
}

func (c *cDict) UpdateDict(ctx context.Context, req *admin.DictUpdateReq) (res *admin.DictUpdateRes, err error) {
	updataDoc := form.NewBuilder().
		SetIfNotEmpty("group", req.Group).
		SetIfNotEmpty("group_name", req.GroupName).
		SetIfNotEmpty("label", req.Label).
		SetIfNotEmpty("value", req.Value).
		SetIfNotEmpty("remark", req.Remark).
		SetIfNotEmpty("status", req.Status).
		Set("updated_at", ztime.GetLocalTime()).
		Build()

	result, err := service.Mgx().UpdateOne(ctx,
		consts.CConfig,
		bson.M{"id": req.ID, "etype": "dict"},
		bson.M{"$set": updataDoc},
	)

	if err != nil {
		g.Log().Error(ctx, "Update error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	if result.MatchedCount == 0 {
		return nil, gerror.NewCode(ecode.DataNotFound)
	}

	return &admin.DictUpdateRes{}, nil
}

func (c *cDict) BatchUpdate(ctx context.Context, req *admin.DictBatchUpdateReq) (res *admin.DictBatchUpdateRes, err error) {
	// rows 是 一个数组 类似 [{id:12,status:normal},..]
	updatedIds := make([]int64, 0)

	for _, item := range req.Rows {
		// 使用类型断言来获取 map 中的值
		id := gconv.Int64(item["id"])
		status, ok := item["status"].(string)
		if !ok {
			g.Log().Errorf(ctx, "Invalid status format in row: %v", item)
			continue
		}

		updateDoc := form.NewBuilder().
			SetIfNotEmpty("status", status).
			Set("updated_at", ztime.GetLocalTime()).
			Build()

		result, err := service.Mgx().UpdateOne(ctx,
			consts.CConfig,
			bson.M{"id": id, "etype": "dict"},
			bson.M{"$set": updateDoc},
		)

		if err != nil {
			g.Log().Errorf(ctx, "Failed to update menu %d: %v", id, err)
			continue
		}

		if result.MatchedCount > 0 {
			updatedIds = append(updatedIds, id)
		}
	}
	return &admin.DictBatchUpdateRes{
		Rows: updatedIds,
	}, nil
}

func (c *cDict) DeleteByID(ctx context.Context, req *admin.DictDeleteReq) (res *admin.DictDeleteRes, err error) {
	updateDoc := form.NewBuilder().
		Set("deleted_at", ztime.GetLocalTime()).
		Build()

	result, err := service.Mgx().UpdateOne(ctx,
		consts.CConfig,
		bson.M{"id": req.Id, "etype": "dict"},
		bson.M{"$set": updateDoc},
	)

	if err != nil {
		g.Log().Error(ctx, "Update error:", err)
		return nil, gerror.NewCode(ecode.InvalidParams)
	}

	if result.MatchedCount == 0 {
		return nil, gerror.NewCode(ecode.DataNotFound)
	}
	return &admin.DictDeleteRes{}, nil
}
